package com.ziytek.web.citizen.service.impl;

import com.ziytek.web.citizen.caffeine.PositionCacheConfig;
import com.ziytek.web.citizen.config.ConfigInit;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.model.bean.OneDetails;
import com.ziytek.web.citizen.model.bean.OneDetailsInfo;
import com.ziytek.web.citizen.util.HexUtil;
import com.ziytek.web.citizen.util.StringUtil;
import com.ziytek.web.citizen.util.VirtualThreadUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * @author fenghx
 * @version 1.0
 * @className BatteryDetailInfo
 * Description: 电池详情信息
 * @date 2024/5/11 11:11
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BatteryDataProcessorServiceImpl {
    private final ConfigInit configInit;
    private final PositionCacheConfig positionCacheConfig;

    public List<OneDetailsInfo> processAllBatteriesDetails(String realData, String cabinetCode, boolean isCapacityData) {
        List<String> dataList = new ArrayList<>();
        for (int i = NumConstant.INT_ZERO; i < NumConstant.INT_SIXTY_FOUR; i++) {
            dataList.add(realData.substring(i * NumConstant.INT_EIGHTY_SIX, (i + NumConstant.INT_ONE) * NumConstant.INT_EIGHTY_SIX));
        }

        // 初始化线程安全的列表
        List<OneDetailsInfo> allBatteriesDetails = Collections.synchronizedList(new ArrayList<>());
        // 使用CompletableFuture来处理异步任务
        List<CompletableFuture<OneDetailsInfo>> futures = new ArrayList<>();

        for (String data : dataList) {
            futureProcess(futures, data, cabinetCode, isCapacityData);
        }

        // 等待所有任务完成，并收集结果
        futures.stream()
                .map(CompletableFuture::join)
                // 过滤掉可能的错误标记值
                .filter(Objects::nonNull)
                .forEach(allBatteriesDetails::add);

        return allBatteriesDetails;
    }

    private void futureProcess(List<CompletableFuture<OneDetailsInfo>> futures, String data, String cabinetCode, boolean isCapacityData) {
        futures.add(CompletableFuture.supplyAsync(() -> getBordData(data, cabinetCode, isCapacityData), VirtualThreadUtil.getExecutor())
                .exceptionally(e -> {
                    // 对异常进行处理，例如记录日志
                    log.error("Error processing data : {}", e.getMessage());
                    return null; // 或者根据需要返回一个特定的错误标记值
                }));
    }

    private OneDetailsInfo getBordData(String data, String cabinetCode, boolean isCapacityData) {
        if (StringUtil.isEmpty(data) || StringUtil.isEmpty(cabinetCode)) {
            return null;
        }

        // 电池容量数据
        if (isCapacityData) {
            return getCapacityBordData(data, cabinetCode);
        }

        // 不是电池容量数据
        OneDetailsInfo oneDetailsInfo = OneDetailsInfo.builder().build();
        String controlAddress = data.substring(NumConstant.INT_ZERO, NumConstant.INT_TWO);
        String version = data.substring(NumConstant.INT_FOUR, NumConstant.INT_SIX);
        data = data.substring(NumConstant.INT_SIX, NumConstant.INT_EIGHTY_SIX);

        // 分控板版本号
        oneDetailsInfo.setControlVersion(controlAddress, version);

        for (int k = NumConstant.INT_ZERO; k < NumConstant.INT_EIGHT; k++) {
            String oneData = data.substring(k * NumConstant.INT_TEN, (k + NumConstant.INT_ONE) * NumConstant.INT_TEN);
            String electricity = oneData.substring(NumConstant.INT_TWO, NumConstant.INT_SIX);
            String voltage = oneData.substring(NumConstant.INT_SIX, NumConstant.INT_TEN);
            String position = oneData.substring(NumConstant.INT_ZERO, NumConstant.INT_TWO);
            int electricityNum = HexUtil.hexToInt(electricity);
            // 电流数据小于5的,视为0
            electricityNum = Math.abs(electricityNum) <= NumConstant.INT_FIVE ? NumConstant.INT_ZERO : electricityNum;
            int voltageNum = HexUtil.hexToInt(voltage);
            // 电流数据小于500的,视为0
            voltageNum = Math.abs(voltageNum) <= NumConstant.INT_FIVE_HUNDRED ? NumConstant.INT_ZERO : voltageNum;

            int positionNum = HexUtil.hexToInt(position);

            String desc = positionCacheConfig.getLinePosition(controlAddress + ServerConstant.DATA_SEPARATOR_SPACE + positionNum);
            String key = cabinetCode + ServerConstant.DATA_SEPARATOR + desc;
            oneDetailsInfo.setOneDetails(key, OneDetails.builder().c(electricityNum).v(voltageNum).build());
        }

        return oneDetailsInfo;
    }

    private OneDetailsInfo getCapacityBordData(String data, String cabinetCode) {
        if (StringUtil.isEmpty(data) || StringUtil.isEmpty(cabinetCode)) {
            return null;
        }

        // 电池容量数据
        OneDetailsInfo oneDetailsInfo = OneDetailsInfo.builder().build();
        String controlAddress = data.substring(NumConstant.INT_ZERO, NumConstant.INT_TWO);
        data = data.substring(NumConstant.INT_SIX, NumConstant.INT_EIGHTY_SIX);

        for (int k = NumConstant.INT_ZERO; k < NumConstant.INT_EIGHT; k++) {
            String oneData = data.substring(k * NumConstant.INT_TEN, (k + NumConstant.INT_ONE) * NumConstant.INT_TEN);
            String capacity = oneData.substring(NumConstant.INT_EIGHT, NumConstant.INT_TEN)
                    + oneData.substring(NumConstant.INT_SIX, NumConstant.INT_EIGHT)
                    + oneData.substring(NumConstant.INT_FOUR, NumConstant.INT_SIX)
                    + oneData.substring(NumConstant.INT_TWO, NumConstant.INT_FOUR);

            String position = oneData.substring(NumConstant.INT_ZERO, NumConstant.INT_TWO);

            String keyDesc = cabinetCode + ServerConstant.DATA_SEPARATOR + controlAddress + ServerConstant.DATA_SEPARATOR + position;
            float capacityNum = NumConstant.FLOAT_ZER;
            try {
                capacityNum = HexUtil.hexStrToFloat(capacity);
            } catch (Exception ignored) {
                // 容量数据异常,视为0
            }

            if (configInit.isPrint()) {
                log.info("本地分容结果位置:{}, capacity原始数据:{}, capacity转换后数据:{}", keyDesc, capacity, capacityNum);
            }
            // 电流数据小于5的,视为0
            capacityNum = Math.abs(capacityNum) <= NumConstant.FLOAT_ZER ? NumConstant.FLOAT_ZER : capacityNum;

            int positionNum = HexUtil.hexToInt(position);

            String desc = positionCacheConfig.getLinePosition(controlAddress + ServerConstant.DATA_SEPARATOR_SPACE + positionNum);
            String key = cabinetCode + ServerConstant.DATA_SEPARATOR + desc;
            oneDetailsInfo.setCapacityMap(key, capacityNum);
        }

        return oneDetailsInfo;
    }
}
